﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Globalization;
using System.Text;
using HTMapLib.Classes;
using MITI;

namespace MapControl.Misc.DAL
{
    public class GPSData
    {
        public int ID;
        public string Name;
        public double LonGPS;
        public double LatGPS;
        public double Alt;
        public double Speed;
        public double Angle;
        public DateTime Time;
        public int SatNum;
        public double Distance;
        public int Airport_Id;
        
        public GPSData(string name, double lon, double lat, double alt, double speed, double angle, DateTime time, int satNum)
        {
            try
            {
                Name = name;
                LonGPS = lon;
                LatGPS = lat;
                Alt = alt;
                Speed = speed;
                Angle = angle;
                Time = time;
                SatNum = satNum;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// Lấy dữ liệu nhận từ cổng COM chuyển thành đối tượng
        /// </summary>
        /// <param name="gpsData"></param>
        public GPSData(string gpsData)
        {
            string[] valueArray;
            try
            {
                //===================================================
                //valueArray = gpsData.Split(new char[1] { ',' });
                //LocalTime = DateTime.Now;
                //Name = valueArray[0];
                //string sign;

                //sign = valueArray[1].Substring(0, 1);
                //double degree = double.Parse(valueArray[1].Substring(1, 2));
                //double minute = double.Parse(valueArray[1].Substring(3));
                //double lat = (minute / 60000f) + degree;
                //LatGPS = HTCollectionHelper.StringCoordToDecimalCoord(sign + lat.ToString("#.00000"));

                //sign = valueArray[2].Substring(0, 1);
                //degree = double.Parse(valueArray[2].Substring(1, 3));
                //minute = double.Parse(valueArray[2].Substring(4));
                //double lon = (minute / 60000f) + degree;
                //LonGPS = HTCollectionHelper.StringCoordToDecimalCoord(sign + lon.ToString("#.00000"));

                //Alt = Double.Parse(valueArray[3]);
                //Speed = Double.Parse(valueArray[4]);
                //Angle = Double.Parse(valueArray[5]);

                //===================================================
                //Name
                int index = 0;
                Name = gpsData.Substring(index, GeneralClass.NAME_LEN);
                index += GeneralClass.NAME_LEN;

                //======================================
                //Lat
                index++; //Bỏ qua vị trí dấu ","
                string value = gpsData.Substring(index, GeneralClass.LAT_LEN);
                string sign;
                sign = value.Substring(0, 1);
                double degree = double.Parse(value.Substring(1, 2));
                double minute = double.Parse(value.Substring(3));
                double lat = (minute / 60000f) + degree;
                LatGPS = HTCollectionHelper.StringCoordToDecimalCoord(sign + lat.ToString("#.00000"));
                index += GeneralClass.LAT_LEN;

                //======================================
                //Lon
                index++; //Bỏ qua vị trí dấu ","
                value = gpsData.Substring(index, GeneralClass.LON_LEN);
                sign = value.Substring(0, 1);
                degree = double.Parse(value.Substring(1, 3));
                minute = double.Parse(value.Substring(4));
                double lon = (minute / 60000f) + degree;
                LonGPS = HTCollectionHelper.StringCoordToDecimalCoord(sign + lon.ToString("#.00000"));
                index += GeneralClass.LON_LEN;

                //======================================
                //Alt
                index++; //Bỏ qua vị trí dấu ","
                
                value = gpsData.Substring(index, GeneralClass.ALT_LEN);
                try
                {
                    Alt = Double.Parse(value);
                }
                catch (Exception ex)
                {
                    Alt = -1;
                }
                
                index += GeneralClass.ALT_LEN;

                //======================================
                //Speed
                index++; //Bỏ qua vị trí dấu ","
                value = gpsData.Substring(index, GeneralClass.SPEED_LEN);
                try
                {
                    Speed = Double.Parse(value);
                }
                catch (Exception ex)
                {
                    Speed = -1;
                }
                index += GeneralClass.SPEED_LEN;

                //======================================
                //Angle
                index++; //Bỏ qua vị trí dấu ","
                value = gpsData.Substring(index, GeneralClass.ANGLE_LEN);
                try
                {
                    Angle = Double.Parse(value);
                }
                catch (Exception ex)
                {
                    Angle = -1;
                }
                index += GeneralClass.ANGLE_LEN;

                //======================================
                //Time
                index++; //Bỏ qua vị trí dấu ","
                value = gpsData.Substring(index, GeneralClass.TIME_LEN);
                try
                {
                    //Chuyển giờ UTC sang giờ Việt nam
                    int hour = int.Parse(value.Substring(0, 2));
                    hour = (hour + 7) % 24;
                    Time = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, hour, int.Parse(value.Substring(2, 2)), int.Parse(value.Substring(4, 2)));

                }
                catch (Exception ex)
                {
                    Time = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, 0, 0, 0);
                }
                index += GeneralClass.TIME_LEN;

                //======================================
                //Number of Sattelines
                index++; //Bỏ qua vị trí dấu ","
                value = gpsData.Substring(index, GeneralClass.SATNUM_LEN);
                try
                {
                    SatNum = int.Parse(value);
                }
                catch (Exception ex)
                {
                    SatNum = -1;
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        

        public GPSData(DataRow row)
        {
            try
            {
                Name = row["name"].ToString();
                LonGPS = double.Parse(row["lon"].ToString());
                LatGPS = double.Parse(row["lat"].ToString());
                Alt = double.Parse(row["alt"].ToString());
                Speed = double.Parse(row["speed"].ToString());
                Angle = double.Parse(row["angle"].ToString());
                Distance = double.Parse(row["distance"].ToString());
                Airport_Id = int.Parse(row["airport_id"].ToString());
                Time = DateTime.Parse(row["time"].ToString());
                SatNum = int.Parse(row["satnum"].ToString());
                
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// Convert instance to byte array
        /// Dùng để test gửi thông tin
        /// </summary>
        /// <returns></returns>
        public char[] ConverToByteArray()
        {
            char[] data = new char[GeneralClass.DATA_LEN];
            char[] comma = new char[1] { ',' };
            char[] hemisphereOUmeridienLat;
            int index = 0;

            //===================================
            //name: 4 byte
            char[] arrValue = Name.ToCharArray(0, GeneralClass.NAME_LEN);
            arrValue.CopyTo(data, index);
            index += arrValue.Length;
            //Add comma
            comma.CopyTo(data, index);

            //===================================
            //lat: 8 byte
            index++;
            double value = LatGPS;
            if (value > 0)
                hemisphereOUmeridienLat = new char[1] { 'N' };
            else
                hemisphereOUmeridienLat = new char[1] { 'S' };
            arrValue = string.Format("{0}{1}", new string(hemisphereOUmeridienLat), Math.Abs(value).ToString("00.00000").Replace(".", "")).ToCharArray(0, GeneralClass.LAT_LEN);
            arrValue.CopyTo(data, index);
            index += arrValue.Length;
            //Add comma
            comma.CopyTo(data, index);

            //===================================
            //lon: 9 byte
            index++;
            value = LonGPS;
            if (LonGPS > 0)
                hemisphereOUmeridienLat = new char[1] { 'E' };
            else
                hemisphereOUmeridienLat = new char[1] { 'W' };
            arrValue = string.Format("{0}{1}", new string(hemisphereOUmeridienLat), Math.Abs(value).ToString("000.00000").Replace(".", "")).ToCharArray(0, GeneralClass.LON_LEN);
            arrValue.CopyTo(data, index);
            index += arrValue.Length;
            //Add comma
            comma.CopyTo(data, index);

            //===================================
            //alt: 4 byte
            index++;
            value = Alt;
            if (value < 10)
                arrValue = string.Format("000{0}", value).ToCharArray(0, GeneralClass.ALT_LEN);
            else if (value < 100)
                arrValue = string.Format("00{0}", value).ToCharArray(0, GeneralClass.ALT_LEN);
            else if (value < 1000)
                arrValue = string.Format("0{0}", value).ToCharArray(0, GeneralClass.ALT_LEN);
            else if (value < 10000)
                arrValue = string.Format("{0}", value).ToCharArray(0, GeneralClass.ALT_LEN);
            else //error
                arrValue = string.Format("-111").ToCharArray();
            arrValue.CopyTo(data, index);
            index += arrValue.Length;
            //Add comma
            comma.CopyTo(data, index);

            //===================================
            //speed: 3 byte
            index++;
            value = Speed;
            if (value < 10)
                arrValue = string.Format("00{0}", value).ToCharArray(0, GeneralClass.SPEED_LEN);
            else if (value < 100)
                arrValue = string.Format("0{0}", value).ToCharArray(0, GeneralClass.SPEED_LEN);
            else if (value < 1000)
                arrValue = string.Format("{0}", value).ToCharArray(0, GeneralClass.SPEED_LEN);
            else //error
                arrValue = string.Format("-11").ToCharArray();
            arrValue.CopyTo(data, index);
            index += arrValue.Length;
            //Add comma
            comma.CopyTo(data, index);

            //===================================
            //angle: 3 byte
            index++;
            value = Angle;
            if (value < 10)
                arrValue = string.Format("00{0}", value).ToCharArray(0, GeneralClass.ANGLE_LEN);
            else if (value < 100)
                arrValue = string.Format("0{0}", value).ToCharArray(0, GeneralClass.ANGLE_LEN);
            else if (value < 1000)
                arrValue = string.Format("{0}", value).ToCharArray(0, GeneralClass.ANGLE_LEN);
            else //error
                arrValue = string.Format("-11").ToCharArray();
            arrValue.CopyTo(data, index);
            index += arrValue.Length;
            //Add comma
            comma.CopyTo(data, index);

            //===================================
            //Time: 6 byte
            index++;
            arrValue = Time.ToString("HHmmss").ToCharArray(0, GeneralClass.TIME_LEN);
            arrValue.CopyTo(data, index);
            index += arrValue.Length;
            //Add comma
            comma.CopyTo(data, index);

            //===================================
            //SatNum: 6 byte
            index++;
            arrValue = SatNum.ToString("0#").ToCharArray(0, GeneralClass.SATNUM_LEN);
            arrValue.CopyTo(data, index);
            return data;
        }

        public override bool Equals(System.Object obj)
        {
            // If parameter is null return false.
            if (obj == null)
            {
                return false;
            }

            // If parameter cannot be cast to Point return false.
            GPSData p = obj as GPSData;
            if ((System.Object)p == null)
            {
                return false;
            }
            
            // Return true if the fields match:
            return (LonGPS == p.LonGPS) && (LatGPS == p.LatGPS) && (Alt == p.Alt) && (Speed == p.Speed) && (Angle == p.Angle) && (Time.Equals(p.Time)) && (SatNum == p.SatNum);
        }

        public bool Equals(GPSData p)
        {
            // If parameter is null return false:
            if ((object)p == null)
            {
                return false;
            }

            // Return true if the fields match:
            return (LonGPS == p.LonGPS) && (LatGPS == p.LatGPS) && (Alt == p.Alt) && (Speed == p.Speed) && (Angle == p.Angle) && (Time.Equals(p.Time)) && (SatNum == p.SatNum);
        }
    }

    public static class GPSDataRepository
    {
        public static string ConnectionString
        {
            get { return BaseDBCe.g_ConnectStr; }
            set { BaseDBCe.g_ConnectStr = value; }
        }

        /// <summary>
        /// Lưu vào CSDL
        /// </summary>
        public static int Save(GPSData gps)
        {
            int currId = -1;
            string sql = "";
            DataTable db;
            try
            {
                //Lưu vào CSDL
                CultureInfo us = new CultureInfo("en-US");
                //Lưu vào CSDL
                sql = string.Format("insert into gpsdata(name, lat, lon, alt, speed, angle, distance, airport_id, time, satnum) values ('{0}',{1},{2},{3},{4},{5},{6},{7},'{8}',{9})",
                   gps.Name, gps.LatGPS.ToString(us), gps.LonGPS.ToString(us), gps.Alt, gps.Speed, gps.Angle, gps.Distance, gps.Airport_Id, gps.Time.ToString("yyyy-MM-dd H:mm:ss"), gps.SatNum);
                BaseDBCe.ExecSql_NoneQuery(sql);
                
                //Trả về id mới thêm vào
                sql = string.Format("select id from gpsdata " +
                                    "where name=N'{0}' and lat={1} and lon={2} and alt={3} and speed={4} and angle={5} and distance={6} and airport_id={7} and time='{8}' and satnum={9}", 
                                    gps.Name, gps.LatGPS, gps.LonGPS, gps.Alt, gps.Speed, gps.Angle, gps.Distance, gps.Airport_Id, gps.Time, gps.SatNum);
                currId = (int)BaseDBCe.ExecSql_DataValue(sql);
            }
            catch (Exception ex)
            {
                string msg = ex.Message;
            }
            return currId;
        }

        public static DataTable LoadDatabase(int min, int max)
        {
            string sql;
            if (min == max && max == 0)
                sql = "select * from gpsdata";
            else
                sql = string.Format("select * from gpsdata where id >= {0} and id <= {1}", min, max);

            return BaseDBCe.ExecSql_DataSet(sql).Tables[0];
        }

        public static DataTable LoadDatabase(string code, int min, int max)
        {
            string sql;
            if (min == max && max == 0)
                sql = string.Format("select * from gpsdata where name='{0}'", code);
            else
                sql = string.Format("select * from gpsdata where id >= {0} and id <= {1} and name='{2}'", min, max, code);

            return BaseDBCe.ExecSql_DataSet(sql).Tables[0];
        }

        public static void Delete(int id)
        {
            string sql = string.Format("delete from gpsdata where id = {0}",id);
            BaseDBCe.ExecSql_NoneQuery(sql);
        }

        public static void DeleteAll()
        {
            string sql = "delete from gpsdata";
            BaseDBCe.ExecSql_NoneQuery(sql);
            sql = "ALTER TABLE gpsdata ALTER COLUMN [Id] IDENTITY (1,1)";
            BaseDBCe.ExecSql_NoneQuery(sql);
        }

        public static void UpdateDistance(int id, int distance)
        {
            string sql = string.Format("update gpsdata set distance = {0} where id = {1}", distance, id);
            BaseDBCe.ExecSql_NoneQuery(sql);
        }

        /// <summary>
        /// Lấy danh sách name trong gpsdata
        /// </summary>
        /// <returns></returns>
        public static DataTable GetPlaneNames()
        {
            string sql = "select distinct name from gpsdata";
            return BaseDBCe.ExecSql_DataSet(sql).Tables[0];
        }
        
        ///// <summary>
        ///// 2014-11-03
        ///// Kiểm tra xem column đã được update chưa.
        ///// True: đã được update, false: chưa được update
        ///// Ghi chú: Update này dùng cho trường hợp truy cập các file CSDL cũ chưa thay đổi theo cấu trúc
        ///// </summary>
        ///// <returns></returns>
        //public static bool IsAlterColumn_Name()
        //{
        //    bool isUpdate = false;
        //    //Kiểm tra xem column name đã cập nhật sang kiểu navarchar(10) chưa
        //    string sql = "SELECT DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'gpsdata' AND COLUMN_NAME = 'name'";
        //    string data_type = BaseDBCe.ExecSql_DataValue(sql).ToString();
        //    //Nếu chưa thì cập nhật 
        //    if (data_type.Contains("nvarchar"))
        //    {
        //        isUpdate = true;
        //    }
        //    return isUpdate;
        //}

        ///// <summary>
        ///// 2014-11-03
        ///// Thay đổi cấu trúc column name trong bảng gpsdata
        ///// Dùng cho trường hợp name này lấy từ table plane thay cho name lấy từ gps
        ///// Ghi chú: Update này dùng cho trường hợp truy cập các file CSDL cũ chưa thay đổi theo cấu trúc
        ///// </summary>
        ///// <returns></returns>
        //public static void AlterColumn_Name()
        //{
        //    string sql = "ALTER TABLE gpsdata ALTER COLUMN name nvarchar(10)";
        //    BaseDBCe.ExecSql_NoneQuery(sql);
        //}

        ///// <summary>
        ///// Cập nhật giá trị của column name
        ///// </summary>
        ///// <param name="code"></param>
        ///// <param name="name"></param>
        //public static void UpdateColumnValue_Name(string code, string name)
        //{
        //    string sql = string.Format("update gpsdata set name = '{0}' where code = '{1}'", name, code);
        //    BaseDBCe.ExecSql_NoneQuery(sql);
        //}

    }

}
